// 数据类型
// formConfig = {
//   rules: {},
//   elements: []
// };
// 每个组件必须加
import { Vue, Component, Watch, Prop } from "vue-property-decorator";
// 每个组件必须加
@Component
export default class ddBuildForm extends Vue {
  formValues: any = this.mergeValues()
  updating: boolean = false
  @Prop({
    type: Object,
    default() {
      return {};
    }
  })
  model!: any;

  @Prop({
    type: Object,
    default() {
      return {};
    }
  })
  config!: any;

  @Prop({
    type: String,
    default: "medium"
  })
  size!: string;

  @Prop({
    type: String,
    default: "80px"
  })
  labelWidth!: string;

  @Watch("formValues", { deep: true })
  getFormValues(formValues) {
    this.updating = true;
    this.$emit("input", formValues);
  }

  @Watch("model", { deep: true })
  getModel() {
    if (!this.updating) {
      this.formValues = this.mergeValues();
    } else {
      this.updating = false;
    }
  }

  // 获取v-model的值
  mergeValues() {
    const vm = this;
    const { model } = vm;
    const defaultValues: any = {};

    this.config.elements.forEach(({ tag, detail = {} }: any) => {
      let { defaultValue = null, name } = detail

      // el-checkbox, el-select multiple 返回数据是[]
      if (tag === "el-checkbox" || (tag === "el-select" && detail.multiple)) {
        // 默认值，下拉框多选， defaultValue 是数组
        defaultValue = defaultValue != null ? defaultValue : []
      }

      defaultValues[name] = defaultValue
    })

    // 返回v-model的值
    return {
      ...defaultValues,
      ...model
    }
  }

  // 就是过滤value 为string， number， boolean 类型的
  filterAttrs(detail: any = {}) {
    // 获取json 的key ,[key1, key2, key3,...]
    const keys = Object.keys(detail);
    const attrs = {};

    keys.forEach(key => {
      const value = detail[key];

      if (
        typeof value === "number" ||
        typeof value === "string" ||
        typeof value === "boolean"
      ) {
        attrs[key] = value
      }
    })
    // console.log(attrs, "attrs,--------");
    return attrs
  }

  render(h) {
    const vm = this
    return h(
      "el-form",
      {
        props: {
          model: vm.formValues,
          rules: vm.config.rules,
          labelWidth: vm.labelWidth
        }
      },
      [
        ...(vm.$slots.prepend || []),
        ...(vm.renderFormItems(h) || []),
        ...(vm.$slots.append || [])
      ]
    );
  }

  renderFormItem(h, { tag, item: label = {}, detail = {} }: any, index) {
    const vm = this;
    const { formValues, size } = vm;
    const { name } = detail;
    const value = formValues[name] || null;
    const modelEvents = {
      input: function(value) {
        formValues[name] = value;
      }
    };

    let children: any = [];
    // console.log(index)
    if (tag === "el-select") {
      const select = h(
        tag,
        {
          attrs: {
            ...vm.filterAttrs(detail)
          },
          props: {
            value,
            ...detail
          },
          on: {
            ...modelEvents
          }
        },
        (detail.items || []).map(option => {
          return h("el-option", {
            attrs: {
              ...vm.filterAttrs(option)
            },
            props: {
              key: option.value,
              ...option
            }
          })
        })
      )
      children = [select];
    } else if (tag === "el-checkbox") {
      const checkbox = h(
        "el-checkbox-group",
        {
          attrs: {
            ...vm.filterAttrs(detail)
          },
          props: {
            value,
            ...detail
          },
          on: {
            ...modelEvents
          }
        },
        (detail.items || []).map(option => {
          return h(
            "el-checkbox",
            {
              attrs: {
                ...vm.filterAttrs(option)
              },
              props: {
                key: option.value,
                label: option.value,
                ...option
              }
            },
            [option.text]
          );
        })
      );
      children = [checkbox];
    } else if (tag === "el-radio") {
      const radios = (detail.items || []).map(option => {
        option = {
          name: detail.name,
          ...option
        };
        return h(
          tag,
          {
            attrs: {
              ...vm.filterAttrs(option)
            },
            props: {
              value,
              ...option
            },
            on: {
              ...modelEvents
            }
          },
          [option.text]
        );
      });
      children = [...radios];
    } else {
      const input = h(tag || "el-input", {
        attrs: {
          ...vm.filterAttrs(detail)
        },
        props: {
          value,
          ...detail
        },
        on: {
          ...modelEvents
        }
      });
      children = [input];
    }

    return h(
      "el-form-item",
      {
        props: {
          size,
          prop: name,
          ...label
        }
      },
      children
    );
  }

  renderFormItems(h) {
    const vm = this;
    return this.config.elements.map((item, index) => {
      return vm.renderFormItem(h, item, index);
    });
  }
}
